package fr.bda.cloud.data;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlInlineBinaryData;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * This class represent a peace of data
 * 
 * @author BARET
 * @since 21/10/2012
 */
@XmlRootElement(name = "bloc")
public class Bloc {

	/** The bloc UUID */
	@XmlAttribute
	private String id;

	/** The bloc size */
	@XmlAttribute
	private int blocSize;

	/** The data size */
	@XmlAttribute
	private int dataSize;

	/** The bloc data */
	@XmlInlineBinaryData
	private byte[] data;

	/**
	 * Default constructor
	 */
	public Bloc() {

	}

	/**
	 * To initialize the bloc from a string value
	 * 
	 * @param value
	 *            The value of the bloc
	 */
	public Bloc(String value) {
		this(value.getBytes());
	}

	public Bloc(byte[] value) {
		this.blocSize = value.length;
		clear();
		setData(value);
	}

	/**
	 * To initialize the bloc with a size
	 * 
	 * @param size
	 *            The size of the bloc
	 */
	public Bloc(int size) {
		this.blocSize = size;
		clear();
	}

	public void clear() {
		this.data = new byte[blocSize];
		this.dataSize = 0;
	}

	public Bloc xor(Bloc b) {

		byte b1[] = data;
		byte b2[] = b.data;

		int len = (b1.length > b2.length) ? b1.length : b2.length;
		byte res[] = new byte[len];

		for (int i = 0; i < len; i++) {
			if (i < b1.length) {
				if (i < b2.length) {
					res[i] = (byte) (b1[i] ^ b2[i]);
				} else {
					res[i] = (byte) (b1[i] ^ 0);
				}
			} else {
				res[i] = (byte) (0 ^ b2[i]);
			}
		}

		return new Bloc(new String(res));
	}

	public byte[] getData() {
		if (dataSize > 0) {
			byte[] res = new byte[dataSize];
			System.arraycopy(data, 0, res, 0, dataSize);
			return res;
		}

		return new byte[0];
	}

	public void setData(byte[] data) {

		if (data.length > blocSize) {
			throw new RuntimeException("Bloc size out of bound. Bloc capcity is [" + blocSize + "] value capacity is [" + data.length + "]");
		}

		this.dataSize = data.length;
		System.arraycopy(data, 0, this.data, 0, data.length);
	}

	public int getBlocSize() {
		return blocSize;
	}

	public int getDataSize() {
		return dataSize;
	}

	public byte[] getBytes() {
		return data;
	}

	public String getId() {
		return id;
	}

	public void setId(String uuid) {
		this.id = uuid;
	}

	public void setBlocSize(int blocSize) {
		this.blocSize = blocSize;
	}

	public void setDataSize(int dataSize) {
		this.dataSize = dataSize;
	}
}
